package com.dc.juc.example._10_aqs;

import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

/**
 * Description: CountDownLatch  ->  await(long timeout, TimeUnit unit)  设置线程最大等待时间
 *
 *      当线程调用了CountDownLatch对象的该方法后，当前线程会被阻塞,直到下面的情况之一发生才会返回：
 *          - 当所有线程都调用了CountDownLatch对象的countDown方法后,也就是计数器值为0时,这时候会返回true；
 *          - 设置的timeout时间到了，因为超时而返回false;
 *          - 其他线程调用了当前线程的interrupt()方法中断了当前线程,当前线程会抛出InterruptedException异常，然后返回。
 *
 *
 * @author: gdc
 * @date: 2021/8/13
 * @version 1.0
 */
@Slf4j
public class CountDownLatch2 {

    private static final int THREAD_COUNT = 200;

    @SneakyThrows
    public static void main(String[] args){
        ExecutorService threadPool = Executors.newCachedThreadPool();

        final CountDownLatch countDownLatch = new CountDownLatch(THREAD_COUNT);

        for (int i = 0; i < THREAD_COUNT; i++) {

            threadPool.execute(() -> {
                try {
                    test(Thread.currentThread().getId());
                } finally {

                    // countDown() 方法放在 finally块中，保证代码肯定会被执行到
                    countDownLatch.countDown();
                }
            });
        }

        // await(long timeout, TimeUnit unit) 方法，使当前线程等待其他线程执行，如果超出最大等待时间
        // 但是存在最大等待时间，超过时间后，继续执行
        countDownLatch.await(10, TimeUnit.MILLISECONDS);
        log.info("finish...");

        // 关闭线程池，调用shutdown()后，会在已经启动的线程执行完之后关闭
        threadPool.shutdown();
    }

    @SneakyThrows
    private static void test(long threadNum) {
        TimeUnit.MILLISECONDS.sleep(100);
        log.info("{}", threadNum);
    }

}
